package com.example.test.controller;
import com.example.test.module.FileInfo;
import com.example.test.module.Response;
import com.example.test.utils.FolderToZipUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipOutputStream;

@RestController
public class FileController {
    private static final Logger log = LoggerFactory.getLogger(FileController.class);
    @RequestMapping(value = "/upload")
    public String upload(@RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return "文件为空";
            }
            // 获取大小
            long size = file.getSize();
            log.info("文件大小： " + size);
           /*// 判断上传文件大小
            if (!FileUtils.checkFileSize(file,50,"M")) {
                log.error("上传文件规定小于50MB");
                return "上传文件规定小于50MB";
            }*/
            // 获取文件名
            String fileName = file.getOriginalFilename();
            log.info("上传的文件名为：" + fileName);
            // 获取文件的后缀名
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            log.info("文件的后缀名为：" + suffixName);
            // 设置文件存储路径
            String filePath = "E:/";
            String path = filePath + fileName;
            File dest = new File(path);
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();// 新建文件夹
            }
            file.transferTo(dest);// 文件写入
            return "上传成功";
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上传失败";
    }

   // 多个文件一起上传
   @PostMapping("/batch")
   public String handleFileUpload(HttpServletRequest request) {
       List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
       MultipartFile file = null;
       BufferedOutputStream stream = null;
       for (int i = 0; i < files.size(); ++i) {
           file = files.get(i);
           String filePath = "E:/";
           if (!file.isEmpty()) {
               try {
                   byte[] bytes = file.getBytes();
                   stream = new BufferedOutputStream(new FileOutputStream(
                           new File(filePath + file.getOriginalFilename())));//设置文件路径及名字
                   stream.write(bytes);// 写入
                   stream.close();
               } catch (Exception e) {
                   stream = null;
                   return "第 " + i + " 个文件上传失败 ==> "
                           + e.getMessage();
               }
           } else {
               return "第 " + i
                       + " 个文件上传失败因为文件为空";
           }
       }
       return "上传成功";
   }

   // 遍历文件目录
   @GetMapping("/findAllFile")
   public Response findAllFile(HttpServletRequest request) {
       String tmpDir = request.getParameter("root");
//       OSInfo.OSType osType = OSInfo.getOSType(); // 操作系统类型
       String osType = System.getProperty("os.name").toLowerCase();
       String rootDir = "";
       if(osType.contains("win")){
           rootDir = "E:\\LS_LSTM\\dataset";
       }
       else{
           rootDir = "/home/wzj/LS_LSTM_proj";
       }
       rootDir = rootDir + tmpDir;
       System.out.println("遍历目录:" + rootDir);

       File dir = new File(rootDir);
       File[] files = dir.listFiles();
       if(files==null){
           return new Response(0,"没有文件");
       }
       // 文件名和文件大小封装为结构体
       FileInfo[] fileInfos = new FileInfo[files.length];
       for (int i = 0; i < files.length; i++) {
           FileInfo fileInfo = new FileInfo();
           // 是否目录
           if(files[i].isDirectory())
               fileInfo.setDir(true);
           else fileInfo.setDir(false);
           // 文件名
           fileInfo.setName(files[i].getName());
           // 文件大小
           double filesize = FileUtils.sizeOf(files[i]) / 1024.0;
           if(filesize > 1048576){
               filesize = filesize / 1024/ 1024;
                // double转换为String

                fileInfo.setSize(String.format("%.2f", filesize) + "\tGB");
           } else if(filesize > 1024){
               filesize = filesize / 1024;
               fileInfo.setSize(String.format("%.2f", filesize) + "\tMB");
              }else{
                fileInfo.setSize(String.format("%.2f", filesize) + "\tKB");
           }
           // 获取文件最后修改时间
           Date date = new Date(files[i].lastModified());
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
           String dateStr = sdf.format(date);
           fileInfo.setTime(dateStr);
           fileInfos[i] = fileInfo;
       }
       Response response = new Response();
       response.setCode(200);
       response.setData(fileInfos);
       return response;
   }

    // 下载文件或文件夹
    @GetMapping("/download")
    public String downloadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String rootDir = "/home/wzj/LS_LSTM_proj";
        String tmpDir = request.getParameter("fileDir");
        String fileDir = rootDir + tmpDir;
        Boolean isDir = false;
        System.out.println("下载目录:" + fileDir);
        if (tmpDir != null) {
            //设置文件路径
            File file = new File(fileDir);
            // 若是目录，先压缩
            if (file.isDirectory()){
                isDir = true;
                System.out.println("文件为目录");
                //这个是压缩之后的文件绝对路径
                FileOutputStream fos = new FileOutputStream(fileDir+".zip");
                ZipOutputStream zipOut = new ZipOutputStream(fos);
                FolderToZipUtil.zipFile(file, file.getName(), zipOut);
                zipOut.close();
                fos.close();

                tmpDir = tmpDir + ".zip";
                fileDir = rootDir + tmpDir;
                System.out.println("new 下载目录:" + fileDir);
                file = new File(fileDir);
            }
            //File file = new File(realPath , fileName);
            // 若文件存在
            if (file.isFile() && file.exists()) {
                System.out.println("文件为文件");
                response.setContentType("application/force-download");// 设置强制下载不打开
                response.addHeader("Content-Disposition", "attachment;fileName=" + tmpDir);// 设置文件名
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);
                    int totalSize = fis.available(); //获取文件大小
                    System.out.println("当前文件下载大小size="+ totalSize);
                    response.setHeader("Content-Length", totalSize+"");

                    bis = new BufferedInputStream(fis);
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    System.out.println("download success");
                    if(isDir) {
                        if (file.delete())
                            System.out.println(file.getName() + " is deleted");
                        else
                            System.out.println(file.getName() + " fail deleted");
                    }
                    return "下载成功";
                } catch (Exception e) {
                    e.printStackTrace();
                } finally { // 做关闭操作
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }

        }
        return "下载失败";
    }

    // 根据Pcap构造对应的长度序列
    @PostMapping("/getLenSeqFromPcap")
    public Response getLenSeqFromPcap(HttpServletRequest request) throws IOException {
        request.setCharacterEncoding("UTF-8");
        String url = request.getRequestURL().toString();
        System.out.println("url:" + url);
        // 获取post请求体的内容
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String name = enu.nextElement();
            System.out.println(name + ": " + request.getParameter(name));
        }
        String tmpDir = request.getParameter("tmpDir");
        String targetProto = request.getParameter("targetProto");
        String targetDir[] = request.getParameter("targetDir").split(",");

        // 构造python调用命令
        List<String> params = new ArrayList<String>();
        params.add("python3");
        params.add("flow-extraction.py");
        params.add(tmpDir);
        params.add("44"); // 暂时固定
        params.add(targetProto);
        for(String target : targetDir){
            params.add(target);
        }
        // 执行py命令
        ProcessBuilder processBuilder = new ProcessBuilder(params);
        System.out.println("调用python");
        processBuilder.redirectErrorStream(true);
        processBuilder.directory(new File("/home/wzj/LS_LSTM_proj"));
        Process process = processBuilder.start();

        // 获取进程的输出流
        Boolean Endflag = false;
        BufferedReader br = null;
        br = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
        String line, res = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
            if (line.contains("finish")) {
                Endflag = true;
                String[] tmp = line.split(" ");
                res = tmp[tmp.length - 1];
                System.out.println("** Finish all **");
            }
        }
        if(Endflag == true) {
            process.destroy();
        }
        Response response = new Response(200, res, "success");
        return response;
    }

    // 根据Pcap构造对应的统计特征
    @PostMapping("/getStaticFeatureFromPcap")
    public Response getStaticFeatureFromPcap(HttpServletRequest request) throws IOException {
        request.setCharacterEncoding("UTF-8");
        String url = request.getRequestURL().toString();
        System.out.println("url:" + url);
        // 获取post请求体的内容
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String name = enu.nextElement();
            System.out.println(name + ": " + request.getParameter(name));
        }
        String targetDir = request.getParameter("targetDir");

        // 构造python调用命令
        List<String> params = new ArrayList<String>();
        params.add("python3");
        params.add("main.py");
        params.add("/home/wzj/LS_LSTM_proj"+targetDir);

        // 执行py命令
        ProcessBuilder processBuilder = new ProcessBuilder(params);
        System.out.println("调用python");
        processBuilder.redirectErrorStream(true);
        processBuilder.directory(new File("/home/wzj/A4C_pcap"));
        Process process = processBuilder.start();

        // 获取进程的输出流
        Boolean Endflag = false;
        BufferedReader br = null;
        br = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
        String line, res = null;
        List<Map<String, String>> resList = new ArrayList<Map<String, String>>();
        Response response = null;

        while ((line = br.readLine()) != null) {
            System.out.println(line);
            if (line.contains("OK")) {
                Endflag = true;
                System.out.println("** Finish all **");
            }
        }
        if(Endflag == true) {
            process.destroy();
            // fileName为按/分割的最后一个字符串
//            System.out.println(targetDir.split("/").length);
            String fileName = targetDir.split("/")[targetDir.split("/").length - 1].split(".pcap")[0];
            System.out.println("/home/wzj/A4C_pcap/results" + "/" + fileName + "_fea.csv");
            File file = new File("/home/wzj/A4C_pcap/results" + "/" + fileName + "_fea.csv");
            if(file.exists()) {
                System.out.println("文件存在");
                // 读csv文件，将第二行数据与第一行标题进行匹配，将第二行数据放入map

                BufferedReader br2 = new BufferedReader(new FileReader(file));
                String[] headLine = br2.readLine().split(",");
                while((line = br2.readLine()) != null) {
                    String[] dataLine = line.split(",");
                    Map<String, String> map = new HashMap<String, String>();
                    for(int i = 0; i < headLine.length; i++){
                        map.put(headLine[i], dataLine[i]);
                    }
                    resList.add(map);
                }
//                System.out.println(headLine.length +" "+ dataLine.length);
//                res = new ObjectMapper().writeValueAsString(map);
//                System.out.println(res);

//                while ((line = br2.readLine()) != null) {
//                    String[] tmp = line.split(",");
//                    for(String str : tmp){
//                        System.out.println(str);
//                    }
//                }
                response = new Response(200, resList, fileName+".pcap");
            }
            else {
                System.out.println("文件:"+fileName+"不存在!");
                response = new Response(500, "文件不存在");
            }
        }
        return response;
    }
}

